package com.tmt.im.common.yunxin;

import com.alibaba.fastjson2.JSONObject;
import com.tmt.springboot.common.restful.ExecuteResult;
import com.tmt.springboot.common.restful.IExecuteResult;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.springframework.http.*;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;

import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * 云信助手类
 *
 * @Description TODO
 * @Author wuyi
 * @Date 2024/8/23 12:49
 * @Version 1.0
 **/
@Slf4j
public class YunXinHelper {

    public static RestTemplate restTemplate = null;

    public static JSONObject exchange(String url, HttpMethod method, MultiValueMap<String, Object> param, IYunXinConfig yunXinConfig) throws Exception {
        Duration curTime = Duration.ofMillis(new Date().getTime());
        String strCurTime = "" + curTime.getSeconds();
        String nonce = UUID.randomUUID().toString().replace("-", "");

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        headers.setAcceptCharset(List.of(StandardCharsets.UTF_8));
        headers.add("AppKey", yunXinConfig.getAppKey());
        headers.add("CurTime", strCurTime);
        headers.add("Nonce", nonce);
        headers.add("CheckSum", CheckSumHelper.getCheckSum(yunXinConfig.getAppSecret(), nonce, strCurTime));

        HttpEntity<MultiValueMap<String, Object>> entity = new HttpEntity<>(param, headers);
        ResponseEntity<JSONObject> responseEntity = restTemplate.exchange(url, method, entity, JSONObject.class);
        if (responseEntity.getStatusCode() != HttpStatusCode.valueOf(200)) {
            throw new Exception("云信请求失败");
        }
        JSONObject jsonResponse = responseEntity.getBody();
        if (jsonResponse == null) {
            throw new Exception("云信请求应答为null");
        }
        return jsonResponse;
    }

    public static JSONObject exchange(String url, HttpMethod method, Map<String, Object> param, IYunXinConfig yunXinConfig) throws Exception {
        Duration curTime = Duration.ofMillis(new Date().getTime());
        String strCurTime = "" + curTime.getSeconds();
        String nonce = UUID.randomUUID().toString().replace("-", "");

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        headers.setAcceptCharset(List.of(StandardCharsets.UTF_8));
        headers.add("AppKey", yunXinConfig.getAppKey());
        headers.add("CurTime", strCurTime);
        headers.add("Nonce", nonce);
        headers.add("CheckSum", CheckSumHelper.getCheckSum(yunXinConfig.getAppSecret(), nonce, strCurTime));

        HttpEntity<Map<String, Object>> entity = new HttpEntity<>(param, headers);
        ResponseEntity<JSONObject> responseEntity = restTemplate.exchange(url, method, entity, JSONObject.class);
        if (responseEntity.getStatusCode() != HttpStatusCode.valueOf(200)) {
            throw new Exception("云信请求失败");
        }
        JSONObject jsonResponse = responseEntity.getBody();
        if (jsonResponse == null) {
            throw new Exception("云信请求应答为null");
        }
        return jsonResponse;
    }

    public static IExecuteResult<Boolean> checkRequest(String appKey, String appSecret, HttpServletRequest request) {
        try {
            byte[] body = new byte[request.getContentLength()];
            IOUtils.readFully(request.getInputStream(), body);
            String requestBody = new String(body, StandardCharsets.UTF_8);

            String AppKey = request.getHeader("AppKey");
            if (!StringUtils.hasText(AppKey)) {
                return ExecuteResult.failure(414, "AppKey参数读取失败", false);
            }

            String CurTime = request.getHeader("CurTime");
            if (!StringUtils.hasText(CurTime)) {
                return ExecuteResult.failure(414, "CurTime参数读取失败", false);
            }

            String MD5 = request.getHeader("MD5");
            if (!StringUtils.hasText(MD5)) {
                return ExecuteResult.failure(414, "MD5参数读取失败", false);
            }

            String CheckSum = request.getHeader("CheckSum");
            if (!StringUtils.hasText(CheckSum)) {
                return ExecuteResult.failure(414, "CheckSum参数读取失败", false);
            }

            if (!appKey.equals(AppKey)) {
                return ExecuteResult.failure(414, "AppKey参数不匹配", false);
            }

            String verifyMD5 = CheckSumHelper.getMD5(requestBody);
            if (!verifyMD5.equals(MD5)) {
                return ExecuteResult.failure(414, "MD5参数校验失败", false);
            }

            String verifyChecksum = CheckSumHelper.getCheckSum(appSecret, verifyMD5, CurTime);
            if (!verifyChecksum.equals(CheckSum)) {
                return ExecuteResult.failure(414, "CheckSum参数校验失败", false);
            }
            return ExecuteResult.success(true);
        } catch (Exception ex) {
            return ExecuteResult.failure(414, "检验请求头信息出现异常", false);
        }
    }

}
